/*
 * JSMuffin - Another javascript canvas framework.
 * @author xshifty
 */

if (muffin) muffin.Canvas = muffin.Canvas || muffin.Class({
	events:{
		onframechange:function () {	},
		onclick:function () {},
		onmousemove:function () {},
		onmousedown:function () {},
		onmouseup:function () {}
	},
	objects:new Array(),
	imageMap:new Array(),
	playHandle:null,
	
	init:function (defaults_, target_) {
		var target = target_ || muffin.DOM.body || muffin.DOM.tag('body')[0];
		muffin.extend(this, {
			'frameRate':30,
			'width':320,
			'height':240,
			'backgroundColor':'#fff'
		}, defaults_);
		
		this.canvas = muffin.DOM.create('<canvas width="'+this.width+'" height="'+this.height+'"></canvas>');
		target.appendChild(this.canvas);
		
		var self = this;
		muffin.DOM.event('click', this.canvas, function (e) {
			var offset = muffin.DOM.offset(this);
			var coords = {'x':e.clientX - offset.left, 'y':e.clientY - offset.top};
			var object = self.getObjectByCoords(coords.x, coords.y);
			
			if (object) {
				object.events.onclick.apply(object, arguments);
			}
			
			self.events.onclick.apply(self, arguments);
		});
		
		muffin.DOM.event('mousedown', this.canvas, function (e) {
			var offset = muffin.DOM.offset(this);
			var coords = {'x':e.clientX - offset.left, 'y':e.clientY - offset.top};
			var object = self.getObjectByCoords(coords.x, coords.y);
			
			if (object) {
				object.events.mouseDragged = true;
				object.events.onmousedown.apply(object, arguments);
			}
			self.events.mouseDragged = true;
			self.events.onmousedown.apply(self, arguments);
		});
		
		muffin.DOM.event('mouseup', this.canvas, function (e) {
			var offset = muffin.DOM.offset(this);
			var coords = {'x':e.clientX - offset.left, 'y':e.clientY - offset.top};
			var object = self.getObjectByCoords(coords.x, coords.y);
			
			if (object) {
				object.events.mouseDragged = false;
				object.events.onmouseup.apply(object, arguments);
			}
			self.events.mouseDragged = false;
			self.events.onmouseup.apply(self, arguments);
		});
		
		muffin.DOM.event('mousemove', this.canvas, function (e) {
			var offset = muffin.DOM.offset(this);
			var coords = {'x':e.clientX - offset.left, 'y':e.clientY - offset.top};
			var object = self.getObjectByCoords(coords.x, coords.y);
			
			if (object) {
				object.events.onmousemove.apply(object, [coords]);
			}
			self.events.onmousemove.apply(self, [coords]);
		});
		
		this.ctx = this.canvas.getContext('2d');
		this.update();
	},
	getObjectByCoords:function (x_, y_, pos_) {
		var x = x_ ? x_ : false;
		var y = y_ ? y_ : false;
		var pos = pos_ ? pos_ : false;
		
		for (var i = this.objects.length-1; i >= 0; i--) {
			var object = this.objects[i];
			var bound = object.getBounds();
			
			if ((x >= bound.x && x <= bound.x+bound.width) && (y >= bound.y && y <= bound.y+bound.height))
				return pos ? i : object;
		}
		
		return false;
	},
	isPlaying:function () {
		return this.playHandle !== null;
	},
	update:function () {
		this.ctx.fillStyle = this.backgroundColor;
		this.ctx.fillRect(0, 0, this.width, this.height);

		for (var i in this.objects) if (this.objects[i].renderize) {
			this.objects[i].renderize(this.ctx);
		}
		return this;
	},
	play:function () {
		if (this.playHandle === null) {
			var self = this;
			self.update();
			this.playHandle = setInterval(function () {
				self.update();
				if (self.events['onframechange']) {
					self.events['onframechange'].apply(self);
				}
			}, 1000 / this.frameRate);
		}
		return this;
	},
	stop:function () {
		if (this.playHandle !== null) {
			clearInterval(this.playHandle);
			this.playHandle = null;
		}
		return this;
	},
	hasAddedObject:function (object_) {
		for (i in this.objects) if (this.objects[i] === object_)
			return true;
		return false;
	},
	addObject:function (object_) {
		this.objects.push(object_);
	},
	getObjects:function () {
		return this.objects;
	}
});